package com.dsg.service.apply.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.DateUtils;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.dao.apply.DsgApplyDdaMapper;
import com.dsg.entity.account.DsgAccountSetting;
import com.dsg.entity.apply.*;
import com.dsg.entity.approve.DsgApproveCase;
import com.dsg.entity.dto.ApplyStatusDto;
import com.dsg.entity.system.DsgSysFile;
import com.dsg.service.DsgServiceImpl;
import com.dsg.service.account.IDsgAccountSettingService;
import com.dsg.service.apply.IDsgApplyDdaService;
import com.dsg.service.apply.IDsgApplyDdaSubService;
import com.dsg.service.apply.IDsgApplyPayService;
import com.dsg.service.apply.IDsgApplyStatusService;
import com.dsg.service.approve.IDsgApproveCaseService;
import com.dsg.service.system.IDsgSysFileService;
import com.dsg.util.Constant;
import com.dsg.util.RRException;
import com.dsg.workflow.WorkflowEngine;
import com.dsg.workflow.WorkflowService3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * DDA設立記錄 服务实现类
 * </p>
 *
 * @author system
 * @since 2020-10-06
 */
@Service
public class DsgApplyDdaServiceImpl extends DsgServiceImpl<DsgApplyDdaMapper, DsgApplyDda> implements IDsgApplyDdaService {
    @Autowired
    IDsgApplyPayService payService;
    @Autowired
    IDsgSysFileService fileService;
    @Autowired
    IDsgApplyDdaSubService subService;
    @Autowired
    private DsgApplyDdaMapper dsgApplyDdaMapper;
    @Autowired
    private IDsgApplyPayService dsgApplyPayService;
    @Autowired
    private IDsgApplyDdaSubService dsgApplyDdaSubService;
    @Autowired
    private IDsgApplyStatusService dsgApplyStatusService;
    @Autowired
    private IDsgApproveCaseService caseService;
    @Autowired
    private WorkflowEngine engine;
    @Autowired
    private IDsgAccountSettingService dsgAccountSettingService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void genDda(DsgApplyBill bill) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", bill.getMainNo());
        wrapper.in("PAY_MODE", DsgApplyPay.PAY_MODE_DAY_ATP, DsgApplyPay.PAY_MODE_HALF_MONTH_ATP,
                DsgApplyPay.PAY_MODE_MONTH_ATP, DsgApplyPay.PAY_MODE_WEEK_ATP);
        List<DsgApplyPay> payList = payService.list(wrapper);
        for (DsgApplyPay pay : payList) {
            wrapper = new QueryWrapper();
            wrapper.eq("PAY_ID", pay.getOid());
            if (count(wrapper) > 0) {
                continue;
            }

            DsgApplyDda dda = new DsgApplyDda();
            dda.setOid(UUIDGenerator.getUUID());
            dda.setPayId(pay.getOid());
            dda.setAppType(bill.getAppType());
            dda.setDdaStatus(DsgApplyDda.DDA_STATUS_NOT_RECORD);
            dda.setEabStatus(DsgApplyDda.EAB_STATUS_UNEFFECT);

            wrapper = new QueryWrapper();
            wrapper.eq("REL_ID", pay.getOid());
            List<DsgSysFile> fileList = fileService.list(wrapper);
            dda.setNewNum(fileList.size());
            List<DsgApplyDdaSub> subList = new ArrayList<>();
            for (DsgSysFile file : fileList) {
                DsgApplyDdaSub sub = new DsgApplyDdaSub();
                sub.setOid(UUIDGenerator.getUUID());
                sub.setPid(dda.getOid());
                sub.setAppNo(bill.getAppNo());
                sub.setRelId(file.getOid());
                sub.setAppType(bill.getAppType());
                sub.setDdaType(DsgApplyDdaSub.DDA_TYPE_RESULT);
                sub.setDdaStatus(DsgApplyDda.DDA_STATUS_NOT_RECORD);
                subList.add(sub);
            }
            if (CollectionUtil.isNotEmpty(subList)) {
                subService.saveBatch(subList);
            }
            save(dda);
        }
    }


    @Override
    public Page<DsgApplyDda> selectByCusDdaList(Page<DsgApplyDda> page, DsgApplyDda dsgApplyDda) {
//        dsgApplyDda.setUserId(SingletonLoginUtils.getSystemUserId());
        return page.setRecords(dsgApplyDdaMapper.selectByCusDdaList(page, dsgApplyDda));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importDda(List<String> list) {
        int i = 17;
        int size = 5;
        String data;
        if (StringUtil.isNotEmpty(list.get(i))) {
            SystemAuthorizingUser user = SingletonLoginUtils.getSystemUser();
            String payLimit;
            List<DsgApplyDda> dsgApplyDdaList = new ArrayList<>();
            for (int j = 0; j < size; j++) {
                data = list.get(i);
                if (StringUtil.isNotEmpty(data)) {
                    DsgApplyDda dsgApplyDda = new DsgApplyDda();
                    //銀行賬號
                    dsgApplyDda.setPayAccountNo(data.substring(43, 61).trim());
                    payLimit = (data.substring(89, 99)).replaceAll(",", "").trim();
                    dsgApplyDda.setPayLimit(StringUtil.isEmpty(payLimit) ? BigDecimal.ZERO : new BigDecimal(payLimit));
                    dsgApplyDda.setPrdty(data.substring(101, 104).trim());
                    dsgApplyDda.setExpiryDate(StringUtil.isEmpty(data.substring(105, 129).trim()) ? null : DateUtils.parseDate(data.substring(105, 129).trim()));
                    if (StringUtil.isNotEmpty(dsgApplyDda.getPayAccountNo())) {
                        dsgApplyDdaList.add(dsgApplyDda);
                    }
                    i++;
                } else {
                    break;
                }
            }
            //回填繳款資料和DDA設立記錄
            if (CollectionUtil.isNotEmpty(dsgApplyDdaList)) {
                DsgApplyDda dsgApplyDda = new DsgApplyDda();
                dsgApplyDda.setNodeName(WorkflowService3.NODE_DDA);
                dsgApplyDda.setPayAccountNos(String.join(",", dsgApplyDdaList.stream().map(DsgApplyDda::getPayAccountNo).collect(Collectors.toList())));
                dsgApplyDda.setEntCode(user.getOrgCode());
                dsgApplyDda.setUserId(user.getUserId());
                List<DsgApplyDda> dsgApplyDdas = dsgApplyDdaMapper.selectByCusDdaList(dsgApplyDda);
                //DDA子表
                QueryWrapper<DsgApplyDdaSub> ddaSubQueryWrapper = new QueryWrapper<>();
                ddaSubQueryWrapper.eq("DDA_STATUS", DsgApplyDda.DDA_STATUS_RECORD);
                ddaSubQueryWrapper.in("PID", dsgApplyDdas.stream().map(DsgApplyDda::getOid).collect(Collectors.toList()));
                List<DsgApplyDdaSub> dsgApplyDdaSubList = dsgApplyDdaSubService.list(ddaSubQueryWrapper);
                //業務單狀態
                ApplyStatusDto applyStatusDto = new ApplyStatusDto();
                applyStatusDto.setEntCode(user.getOrgCode());
                applyStatusDto.setPayAccountNos(String.join(",", dsgApplyDdaList.stream().map(DsgApplyDda::getPayAccountNo).collect(Collectors.toList())));
                List<ApplyStatusDto> applyStatusDtoList = dsgApplyStatusService.getDsgApplyStatusList(applyStatusDto);
                List<DsgApplyStatus> dsgApplyStatusList = new ArrayList<>();
                Date date = new Date();
                dsgApplyDdas.forEach(I -> {
                    dsgApplyDdaList.forEach(J -> {
                        if (I.getPayAccountNo().equals(J.getPayAccountNo())) {
                            //DDA設立記錄
                            I.setOptNum(I.getOptNum().intValue() + 1);
                            I.setDdaStatus(DsgApplyDda.DDA_STATUS_SUCCESS);
                            I.setEabStatus(DsgApplyDda.EAB_STATUS_EFFECT);
                        }
                    });
                    dsgApplyDdaSubList.forEach(K -> {
                        if (I.getOid().equals(K.getPid())) {
                            K.setDdaStatus(DsgApplyDda.DDA_STATUS_SUCCESS);
                            K.setDdaType(DsgApplyDdaSub.DDA_TYPE_RESULT);
                            K.setUploadTime(date);
                        }
                    });
                    applyStatusDtoList.forEach(L -> {
                        if (I.getPayAccountNo().equals(L.getPayAccountNo())) {
                            DsgApplyStatus dsgApplyStatus = new DsgApplyStatus();
                            dsgApplyStatus.setOid(L.getOid());
                            dsgApplyStatus.setIsDda(DsgApplyStatus.AppStatus.yes.getCode());
                            dsgApplyStatusList.add(dsgApplyStatus);
                        }
                    });
                });
                if (CollectionUtil.isNotEmpty(dsgApplyDdas)) {
                    updateBatchById(dsgApplyDdas);
                    if (CollectionUtil.isNotEmpty(dsgApplyStatusList)) {
                        dsgApplyStatusService.updateBatchById(dsgApplyStatusList);
                    } else {
                        throw new RRException("未查詢到DDA子表數據");
                    }
                    //繳款資料
                    QueryWrapper<DsgApplyPay> queryWrapper = new QueryWrapper<>();
                    queryWrapper.in("OID", String.join(",", dsgApplyDdas.stream().map(DsgApplyDda::getPayOid).collect(Collectors.toList())));
                    List<DsgApplyPay> dsgApplyPayList = dsgApplyPayService.list(queryWrapper);
                    if (CollectionUtil.isNotEmpty(dsgApplyPayList)) {
                        //天鑽收款銀行帳戶
                        QueryWrapper<DsgAccountSetting> settingQueryWrapper = new QueryWrapper<>();
                        settingQueryWrapper.eq("ENT_CODE ", SingletonLoginUtils.getSystemEntCode());
                        settingQueryWrapper.eq("PAY_METHOD ", Constant.PAY_TYPE_CDC);
                        settingQueryWrapper.eq("ACCOUNT_NO ", String.join(",", dsgApplyPayList.stream().map(DsgApplyPay::getAccountNo).collect(Collectors.toList())));
                        List<DsgAccountSetting> settingList = dsgAccountSettingService.list(settingQueryWrapper);
                        dsgApplyPayList.forEach(I -> {
                            dsgApplyDdaList.forEach(J -> {
                                if (I.getPayAccountNo().equals(J.getPayAccountNo())) {
                                    I.setPayLimit(J.getPayLimit());
                                    I.setPRDTY(J.getPrdty());
                                    I.setExpiryDate(J.getExpiryDate());
                                    settingList.forEach(K -> {
                                        if (K.getAccountNo().equals(I.getAccountNo())) {
                                            I.setPayStatus(DsgApplyPay.PAY_STATUS_IN_USE);
                                        }
                                    });
                                }
                            });
                        });
                        dsgApplyPayService.updateBatchById(dsgApplyPayList);
                    }
                    if (CollectionUtil.isNotEmpty(dsgApplyDdaSubList)) {
                        dsgApplyDdaSubService.updateBatchById(dsgApplyDdaSubList);
                        for (DsgApplyDdaSub dsgApplyDdaSub : dsgApplyDdaSubList) {
                            DsgApproveCase approveCase = caseService.getCase(WorkflowService3.NODE_DDA, dsgApplyDdaSub.getAppNo());
                            if (approveCase == null) {
                                throw new RRException("對單CASE不存在");
                            }
                            try {
                                if (DsgApproveCase.Status.started.getCode().intValue() == approveCase.getStatus().intValue()) {
                                    engine.forward(approveCase);
                                }
                            } catch (Exception e) {
                                log.error("推實例異常：", e);
                                throw new RRException("推實例異常");
                            }
                        }
                    }
                } else {
                    throw new RRException("未查詢到DDA數據");
                }
            }
        }
    }

    @Override
    public void importDdaChange(List<String> list) {
        int i = 19;
        int size = 5;
        String data;
        if (StringUtil.isNotEmpty(list.get(i))) {
            String payLimit;
            List<DsgApplyDda> dsgApplyDdaList = new ArrayList<>();
            for (int j = 0; j < size; j++) {
                data = list.get(i);
                if (StringUtil.isNotEmpty(data)) {
                    DsgApplyDda dsgApplyDda = new DsgApplyDda();
                    //銀行賬號
                    dsgApplyDda.setPayAccountNo(data.substring(41, 59));
                    payLimit = data.substring(90, 100);
                    dsgApplyDda.setPayLimit(StringUtil.isEmpty(payLimit) ? BigDecimal.ZERO : new BigDecimal(data.substring(91, 101)));
                    dsgApplyDda.setPrdty(data.substring(102, 105));
                    dsgApplyDdaList.add(dsgApplyDda);
                    i++;
                } else {
                    break;
                }
            }
            //回填繳款資料和DDA設立記錄
            if (CollectionUtil.isNotEmpty(dsgApplyDdaList)) {
                DsgApplyDda dsgApplyDda = new DsgApplyDda();
                dsgApplyDda.setPayAccountNos(String.join(",", dsgApplyDdaList.stream().map(DsgApplyDda::getPayAccountNo).collect(Collectors.toList())));
                List<DsgApplyDda> dsgApplyDdas = dsgApplyDdaMapper.selectByCusDdaList(dsgApplyDda);
                dsgApplyDdas.forEach(I -> {
                    dsgApplyDdaList.forEach(J -> {
                        if (I.getPayAccountNo().equals(J.getPayAccountNo())) {
                            //DDA設立記錄
                            I.setOptNum(I.getOptNum().intValue() + 1);
                        }
                    });
                });
                if (CollectionUtil.isNotEmpty(dsgApplyDdas)) {
                    updateBatchById(dsgApplyDdas);
                    //繳款資料
                    QueryWrapper<DsgApplyPay> queryWrapper = new QueryWrapper<>();
                    queryWrapper.in("OID", String.join(",", dsgApplyDdas.stream().map(DsgApplyDda::getPayOid).collect(Collectors.toList())));
                    List<DsgApplyPay> dsgApplyPayList = dsgApplyPayService.list(queryWrapper);
                    if (CollectionUtil.isNotEmpty(dsgApplyPayList)) {
                        dsgApplyPayList.forEach(I -> {
                            dsgApplyDdaList.forEach(J -> {
                                if (I.getPayAccountNo().equals(J.getPayAccountNo())) {
                                    I.setPayLimit(J.getPayLimit());
                                    I.setPRDTY(J.getPrdty());
                                }
                            });
                        });
                        dsgApplyPayService.updateBatchById(dsgApplyPayList);
                    }
                }
            }
        }
    }
}
